package com.qingfeng.basic_lib.basic

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.LayoutInflater
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.viewbinding.ViewBinding
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.customview.customView
import com.afollestad.materialdialogs.lifecycle.lifecycleOwner
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.ToastUtils
import com.qingfeng.basic_lib.R
import com.qingfeng.basic_lib.event.com.qingfeng.basic_lib.app.MVVMYan
import com.qingfeng.basic_lib.event.com.qingfeng.basic_lib.bean.Message
import java.lang.IllegalArgumentException
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type

abstract class BasicActivity <VM : BasicViewModel, DB : ViewBinding> : AppCompatActivity() {


    protected lateinit var mBinding: DB

    protected lateinit var viewModel: VM

    private var dialog: MaterialDialog? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initSplashMethod()
        initViewDataBinding()
        lifecycle.addObserver(viewModel)
        //注册 UI事件
        registerDefUIChange()
        initView(savedInstanceState)
        setListener()
        initData()
    }




    open fun layoutId(): Int = 0
    open fun initSplashMethod(){}
    open fun setListener(){}
    abstract fun initView(savedInstanceState: Bundle?)
    abstract fun initData()


    private fun initViewDataBinding() {
        val type = javaClass.genericSuperclass
        LogUtils.e("javaClass.genericSuperclass is $type")
        if (type is ParameterizedType) {
            val clazz = type.actualTypeArguments[1] as Class<*>
//            for (actualTypeArgument in type.actualTypeArguments) {
//                LogUtils.e("actualTypeArgument is $actualTypeArgument")
//            }
            when {
                ViewDataBinding::class.java.isAssignableFrom(clazz) && clazz != ViewDataBinding::class.java -> {
                    if (layoutId() == 0) throw IllegalArgumentException("Using DataBinding requires overriding method layoutId")
                    mBinding = DataBindingUtil.setContentView(this, layoutId())
                    (mBinding as ViewDataBinding).lifecycleOwner = this
                }

                ViewBinding::class.java.isAssignableFrom(clazz) && clazz != ViewBinding::class.java -> {
                    clazz.getDeclaredMethod("inflate", LayoutInflater::class.java).let {
                        mBinding = it.invoke(null, layoutInflater) as DB
                        setContentView(mBinding.root)
                    }
                }
                else -> {
                    if (layoutId() == 0) throw IllegalArgumentException("If you don't use ViewBinding, you need to override method layoutId")
                    setContentView(layoutId())
                }
            }
            createViewModel(type.actualTypeArguments[0])
        } else throw IllegalArgumentException("Generic error")


    }


    /**
     * 创建 ViewModel
     */
    private fun createViewModel(type: Type) {
        val clazz = type as? Class<VM> ?: BasicViewModel::class.java
        viewModel = ViewModelProvider(viewModelStore, defaultViewModelProviderFactory).get(clazz) as VM
    }

    private fun registerDefUIChange() {
        viewModel.defUI.showDialog.observe(this, Observer{
            showLoading()
        })
        viewModel.defUI.dismissDialog.observe(this, Observer{
            dismissLoading()
        })
        viewModel.defUI.toastEvent.observe(this,Observer{
            ToastUtils.showShort(it)
        })
        viewModel.defUI.msgEvent.observe(this, Observer{
            handleEvent(it)
        })
    }

    open fun handleEvent(msg: Message) {}

    /**
     * 打开等待框
     */
    private fun showLoading() {
        (dialog ?: MaterialDialog(this)
            .cancelable(false)
            .cornerRadius(8f)
            .customView(R.layout.custom_progress_dialog_view, noVerticalPadding = true)
            .lifecycleOwner(this)
            .maxWidth(R.dimen.dialog_width).also {
                dialog = it
            })
            .show()
    }

    /**
     * 关闭等待框
     */
    private fun dismissLoading() {
        dialog?.run { if (isShowing) dismiss() }
    }



    override fun getDefaultViewModelProviderFactory(): ViewModelProvider.Factory {
        return MVVMYan.getConfig().viewModelFactory() ?: super.getDefaultViewModelProviderFactory()
    }


}